#include <iostream>
#include <vector>
#include <queue>
#define MAXV 5005
#define INF 0x3f3f3f3f
using namespace std;

struct edge { int to, cost; };

vector<edge> G[MAXV];

typedef pair<int, int> P;

priority_queue<P, vector<P>, greater<P>> q;
int V, E;
void solve();
int d[MAXV], ds[MAXV];


int main() {
    cin >> V;
    for (int i = 1; i <= V; i++) {
        cin >> E;
        int to, cost;
        for (int j = 0; j < E; j++) {
            cin >> to >> cost;
            G[i].push_back({to, cost});
        }
    }
    solve();
    return 0;
}

// 次短路u的本质就是:
// 1. v的最短路 + cost(v, u)
// 2. v的次短路 + cost(v, u)
void solve() {
    fill(d, d + MAXV, INF);
    fill(ds, ds + MAXV, INF);
    d[1] = 0;
    q.push({0, 1});
    while (!q.empty()) {
        P p = q.top(); q.pop();
        int u = p.second;
        if (ds[u] < p.first) continue; // 也就是说优先队列中的点无法进行任何更新
        for (edge& e: G[u]) {
            int cost = d[u] + e.cost;
            if (d[e.to] > cost) {
                swap(cost, d[e.to]);
                q.push({d[e.to], e.to});
            }
            if (ds[e.to] > cost && d[e.to] < cost) {
                ds[e.to] = cost;
                q.push({ds[e.to], e.to});
            }
        }
    }
    
}